home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Network Supervisor's Toolkit
/
Network Supervisor's Toolkit.iso
/
tools
/
nwtp06
/
nwfile.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-07-10
|
92KB
|
2,999 lines
{$X+,B-,V-} {essential compiler directives}
Unit nwFile;
{ nwFile unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R. Spronk }
INTERFACE
{ Primary Functions Interrupt: comments:
Volume Management (Volume Tables)
---------------------------------
* ClearObjectVolRestriction (F216/22) (3) [aka ClearVolumeRestrictions/RemoveObjectDiskRestrictions]
* GetObjectVolRestriction (F216/29) (3) [aka GetObjDiskRestrictions/GetObjectDiskUsageAndRestrictions]
* GetVolumeName (F216/06)
* GetVolumeNameWithHandle (F216/15) [aka GetVolumeInfoWithHandle]
* GetVolumeNumber (F216/05)
* GetVolumeUsage (F216/2C) (3) [aka GetExtendedVolumeInformation]
* IsVolumeRemovable (F212) [aka GetVolumeInfoWithNumber]
* ScanVolForRestrictions (F216/20) (3)
* SetObjectVolRestriction (F216/21) (3) [aka SetVolumeRestrictions/SetObjectVolSpaceLimit
/AddUserDiskspaceRestriction]
Directory Handles (Directory Handle Table/Drive tables)
-------------------------------------------------------
* AllocPermanentDirHandle (F216/12)
* AllocTemporaryDirHandle (F216/13)
* DeallocateDirHandle (F216/14)
* DeleteFakeRootDirectory (E906)
* GetDirectoryHandle (E900)
* GetDriveConnectionId (EF02)
* GetDirectoryPath (F216/01)
* GetDriveFlag (EF01) (6)
* GetDriveHandle (EF00) (6)
* GetRelativeDriveDepth (E907)
* GetSearchDriveVector (E901)
* MapFakeRootDirectory (E905)
* SetDirectoryHandle (F216/00)
* SetDriveConnectionId (EF02)
* SetDriveFlag (EF01)
* SetDriveHandle (EF00)
* SetSearchDriveVector (E902)
Secondary Functions
* DeleteConnectionsDriveMappings
* DeleteDriveMapping
* GetEnvPath (BA..)
* IsSearchDrive (BA..)
* IsNetworkDrive (4409)
* MapDrive
* MapPermanentDrive
* MapSearchDrive
* SetEnvPath (BA..)
Entries (directory/file management)
-----------------------------------
* ChangeDirectory (3B..) (DOS)
* ConvertPathToDirEntryId (F217/F4)
* CreateDirectory (F216/0A)
* DeleteDirectory (F216/0B)
* EraseFiles (F244)
. FileServerFileCopy (F3..)
GetDirectoryInfo (F216/2D) (3)
* GetDirectoryEntry (F216/1F) (3)
. GetExtendedFileAttributes (B600) =F24E ???
. GetFileAttributes (4300) (DOS)
* GetTrueEntryName (60..) (DOS)
* MapDirentryIdToPath (F217/F3)
MoveEntry (F216/2E) (3) dir and files
* PurgeSalvagableFile (F216/1D) (3)
* RecoverSalvagebleFile (F216/1C) (3)
* RenameDirectory (F216/0F)
* ScanDirectoryInformation (F216/02)
* ScanDirectoryEntry (F216/1E) (3)
* ScanFileInformation (F217/0F)
ScanFilePhysical (F216/28) (3)
* ScanSalvagableFiles (F216/1B) (3)
* SetEntry (F216/25) (3) dir and files
. SetExtendedFileAttributes (B601) =F24F
. SetFileAttributes (F246) [4301]
* SetFileInformation (F217/10)
* ScanDirRestrictions (F216/23) (3)
* SetDirRestriction (F216/24) (3)
Secondary functions:
DeleteFile
GetFileHandle
IsFileShareable
FlagFileShareable
PurgeFiles (by dirHandle,fileMask)
SalvageFiles (by dirHandle,fileMask)
PurgeAllErasedFiles
Trustees/Max. Rights Mask
-------------------------
* DeleteTrustee (F216/2B) (3)
* GetEffectiveRights (F216/2A) (3)
. ModifyMaximumRightsMask (F216/04)
. ScanBinderyObjectTrusteePaths (F217/47)
* ScanEntryForTrustees (F216/26) (3)
* SetTrustee (F216/27) (3)
Not Implemented:
----------------
- AddTrusteeToDirectory (F216/0D) (10)
- AllocSpecialDirHandle (F216/16) (2)
- DeleteTrusteeFromDirectory (F216/0E) (10)
- FileServerFileCopy (E6..) (8)
- GetEffectiveDirectoryRights (F216/03) (10)
- GetPathFromDirEntryID (F216/1A) (12)
- GetVolumeInformation (F217/E9) (1)
- GetVolumeInfoWithHandle (F216/15) (5)
- GetVolumeInfoWithNumber (F212) (4) [DA..]
- PurgeErasedFiles (F216/10) (8)
- PurgeAllErasedFiles (F217/CE) (8)
- RestoreDirectoryHandle (F216/18) (2)
- RestoreErasedFile (F216/11) (8)
- SaveDirectoryHandle (F216/17) (2)
- ScanDirectoryForTrustees (F216/0C) (9)
- SetDirectoryInformation (F216/19) (11)
- SetFileAttributes (E4..) (7)
- UpdateFileSize (E5..) (7)
Notes: (1) GetVolumeInformation. This call is NOT available in all 3.x versions.
(only with Nw 2.1 & 3.1x and CLIB.NLM dated before 11-11-92 )
This call is not implemented here. Replaced by GetVolumeUsage.
(2) not available in (all versions of) NW 3.x.
(3) NW 3.x (and upwards) only.
(4) Replaced by GetVolumeUsage and IsVolumeRemovable.
(5) Replaced by GetVolumeUsage and GetVolumeNameWithHandle.
(6) Information can also be obtained by calling GetDirectoryHandle.
(DOS) 'Normal' DOS call, extended by NetWare shell.
(7) Not supported by Adv.NW 3.x. Not implemented here.
These are functions using FCB's. If another function with the same
name is listed here, that function performs the same action.
(8) Not supported by Adv.NW 3.x. Not implemented here.
These functions have been replaced with calls marked (3)
(9) Replaced by a newer version: ScanEntryForTrustees.
(10) Replaced by DeleteTrustee, GetEffectiveRights and SetTrustee.
(11) Replaced by SetEntry
(12) Replaced by MapDirEntryIDtoPath
}
Uses nwIntr,nwMisc,nwBindry,nwConn;
Var Result:Word;
Type TsearchDriveVector=array [1..17] of byte;
CONST
DRIVE_UNUSED = $00;
DRIVE_PERMANENT = $01; { Drive permanently assigned to fileserver directory }
DRIVE_TEMPORARY = $02; { Drive temporary assigned to FS dir. Released by EOJ }
DRIVE_NETWORK = $03; { Normal drive mapping }
DRIVE_LOCAL = $80; { Drive is local. ! By ORing with one of the above bits,
it can be reassigned to a FS directory.}
{Name Space Type constants}
NS_DOS =0;
NS_MAC =1;
NS_NFS =2;
NS_FTAM =3;
NS_HPFS =4;
{ Attributes / Netware directory & file attributes }
A_NORMAL = $00; {file}
A_READ_ONLY = $01; {file}
A_HIDDEN = $02; {file/dir}
A_SYSTEM = $04; {file/dir}
A_EXECUTE_ONLY = $08; {file}
A_DIRECTORY = $10; {file}
A_NEEDS_ARCHIVED = $20; {file}
A_undocumented = $40;
A_SHAREABLE = $80; {file}
A_LO_SEARCH = $0100; {file}
A_MID_SEARCH = $0200; {file}
A_HI_SEARCH = $0400; {file}
A_RESERVED = $0800; {file/dir}
A_TRANSACTIONAL = $1000; {file}
A_INDEXED = $2000; {file}
A_READ_AUDIT = $4000; {file}
A_WRITE_AUDIT = $8000; {file}
A_PURGE = $010000; {file/dir}
A_RENAME_INHIBIT = $020000; {file/dir}
A_DELETE_INHIBIT = $040000; {file/dir}
A_COPY_INHIBIT = $080000; {file}
{ Trustee Attributes / directory access rights }
TA_NONE = $00;
TA_READ = $01; {R open/read}
TA_WRITE = $02; {W open/write}
TA_RESERVED = $04; { reserved, set to 0 }
TA_CREATE = $08; {C create files or dirs}
TA_DELETE = $10; {E delete files/dirs}
TA_ACCESS = $20; {A set /delete trustees}
TA_SEARCH = $40; {F directory can be searched/file is visible}
TA_MODIFY = $80; {M modify dir/file attributes}
TA_SUPERVISOR =$100; {S supervisor rights to file or directory }
{ Entry Modify flags / see SetEntry }
EM_ENTRYNAME = $00000001;
EM_ATTRIBUTES = $00000002;
EM_CREATIONTIME = $0000000C; { date = $04, time = $08 }
EM_OWNERID = $00000010;
EM_ARCHIVETIME = $00000060; { date = $20, time = $40 }
EM_ARCHIVERID = $00000080;
EM_MODIFYTIME = $00000300; { date = $0100, time =$0200 }
EM_MODIFIERID = $00000400;
EM_LASTACCESSTIME = $00000800; { date = $0800 }
EM_RIGHTSMASK = $00001000;
EM_MAXDISKSPACE = $00002000;
Type TvolUsage=record
totalBlocks, {static info}
freeBlocks, {dynamic}
purgableBlocks, {dynamic}
notYetPurgableBlocks, {dynamic}
totalDirEntries, {static}
availDirEntries, {dynamic}
Flags :LongInt; {dynamic}
SectorsPerBlock :byte; {static/number of 512 byte sectors per block}
volumeName :string[16];{static}
end;
{ used By ScanVolForRestrictions }
TobjVolRestr=array[1..64] of record
objId :LongInt;
MaxAllowedBlocks:LongInt;
end;
Type Tentry=record
EntryName :String[16];
NSType :byte; {namespace number}
DataForkSize :Longint; { =FileSize when NStype=0 (dos) }
{ResourceForkSize:Longint; (Mac data) =0 when NStype=0 (dos) }
FileSize :Longint; {FileSize=Resource+Data forksize }
Attributes :Longint;
RightsMask :word; {(4)}
CreationTime,
ArchiveTime,
ModifyTime,
LastAccessTime,
DeleteTime :TnovTime; {salvagable file only}
OwnerId,
ArchiverId,
ModifierId,
DeletorId :Longint; {salvagable file only}
end;
{ Note: (4) When used with ScanDirectoryInfo, this field
contains the MaximumRightsMask.
Otherwise, the InheritedRightsMask }
Type TdirRestrList=array[1..56] of record
Level:Byte;
MaxBlocks,
AvailableBlocks:Longint;
end;
{when MaxBlocks and Availableblocks are set to to $7FFFFFFF,
no restrictions are enforced -at this level-}
Type TtrusteeInformation=record
NumberOfTrustees:Byte;
TrusteeID :array[1..20] of Longint;
TrusteeRights:array[1..20] of Word;
end;
{-------------------- Volumes----------------------- }
{F216/05 [2.15c+]}
Function GetVolumeNumber( volumeName:String; Var volumeNumber:Byte ):boolean;
{ Returns the volume number of a given volume name }
{F216/06 [2.15c+]}
Function GetVolumeName( volumeNumber:Byte; Var volumeName:String ):boolean;
{ Returns the volume name of a give volume number [0..31].
If the volume is not mounted at the time of this call, a null-string is returned. }
{F216/2C [2.15c+]}
Function GetVolumeUsage(volumeNumber:byte; Var VolUsage: TvolUsage):boolean;
{F212 [2.15c+]}
Function IsVolumeRemovable( volumeNumber:Byte;
Var volIsRemoveable:Boolean):boolean;
{F216/15 [2.15c+]}
Function GetVolumeNameWithHandle( dirHandle:Byte;
Var volumeName:String ):boolean;
{F216/29 [3.x]}
Function GetObjectVolRestriction(VolumeNumber:byte; objId:LongInt;
Var MaxAllowedBlocks,BlocksInUse:LongInt):boolean;
{F216/21 [3.x]}
Function SetObjectVolRestriction(VolumeNumber:byte; objId,
MaxAllowedBlocks:LongInt):boolean;
{F216/22 [3.x]}
Function ClearObjectVolRestriction(VolumeNumber:byte; objId:LongInt):boolean;
{F216/20 [3.x]}
Function ScanVolForRestrictions(VolumeNumber:byte;
{i/o} Var sequenceNbr:LongInt;
{out} Var NbrOfObjects:byte;
Var ResultBuffer:TobjVolRestr):boolean;
{ 1st call: sequenceNbr=0,
after last call: sequenceNbr=0 again. }
{-------------------- Directory Handles/ Drives -------------}
{F216/01}
Function GetDirectoryPath(DirHandle:byte; Var PathName:string):boolean;
{EF00 [2.0/2.1/3.x]}
Function GetDriveHandle( DriveNumber:Byte; Var DirHandle:Byte ):boolean;
{ The call returns a pointer to the shell's Drive Handle Table. (32 bytes)
(Drives A..Z and temporary drives [\]^_' )
If a drive has been assigned a directory handle on the file server,
the handle can be found in the DHT at the position corresponding with the drive letter.}
{EF00 [2.0/2.1/3.x]}
Function SetDriveHandle( DriveNumber:Byte; DirHandle:Byte ):boolean;
{E900 [2.0/2.1/3.x]}
Function GetDirectoryHandle( DriveNumber:Byte; Var dirHandle,status:byte):Boolean;
{ Returns directory handle and status flags for a drive. }
{ Drivenumber = 0..31 (A..Z = 0..25) and temp drives (26..31) }
{EF01 [2.0/2.1/3.x]}
Function GetDriveFlag( DriveNumber:Byte; Var DriveStatus:Byte ):Boolean;
{ This call returns a pointer to the shell's Drive Flag Table (32 Bytes)
Each entry indicates a drive's status (permanent,temporary,local,unassigned)
For further explanation see the DRIVE_xxx constants.}
{EF01 [2.0/2.1/3.x]}
Function SetDriveFlag( DriveNumber:Byte; DriveStatus:Byte ):Boolean;
{F216/14 [2.15c+]}
function DeallocateDirHandle(DirHandle : Byte) : Boolean;
{ This function deletes a directory handle }
{EF02 [2.0/2.1/3.x]}
Function GetDriveConnectionID( DriveNumber:Byte; Var connID:Byte):boolean;
{ returns the servernumber (1..8) associated with a drive. }
{EF02 [2.0/2.1/3.x]}
Function SetDriveConnectionID( DriveNumber:Byte; connID:Byte):boolean;
{F216/00 [2.15c+]}
Function SetDirectoryHandle( sourceDirHandle:Byte; sourceDirPath:String;
targetDirHandle:Byte ):boolean;
{ make handle 'targetHandle' point to the directory provided by
sourceHandle and/or sourceDirPath. }
{F216/12 [2.15c+]}
FUNCTION AllocPermanentDirHandle( DriveNumber:Byte;
DirHandle : byte; DirPath : string ;
var NewDirHandle, EffectiveRights: byte ) :boolean;
{F216/13 [2.15c+]}
function AllocTemporaryDirHandle( DriveNumber:byte;
DirHandle : Byte; DirPath : String;
var NewDirHandle,EffectiveRights : Byte) : Boolean;
{ Allocates a temporary directory handle, deleted automatically by EOJ. }
{E901}
Function GetSearchDriveVector(Var vector:TsearchDriveVector):boolean;
{E902 }
Function SetSearchDriveVector(vector:TsearchDriveVector):boolean;
{E905 (shell 3.01+)}
Function MapFakeRootDirectory(DriveNumber:byte; DirPath:string):boolean;
{E906 (shell 3.01+)}
Function DeleteFakeRootDirectory(DriveNumber:byte):boolean;
{E907 (shell 3.01+)}
Function GetRelativeDriveDepth(DriveNumber:byte; Var depth:byte):boolean;
{BA.. }
Function GetEnvPath(Var EnvPath:string):boolean;
{BA.. }
Function SetEnvPath(EnvPath:string):boolean;
{secondary }
FUNCTION MapDrive(DriveNumber:byte; DirectoryPath:string;
Root, Permanent:boolean):boolean;
{secondary }
FUNCTION MapPermanentDrive(DriveNumber:byte; DirectoryPath:string;
Root:boolean):boolean;
{secondary}
Function MapSearchDrive(DriveNumber:byte; DirPath:string;
PathPosition:byte;
Insert,Root,Permanent:Boolean):boolean;
{secondary}
Function DeleteDriveMapping(DriveNumber:Byte):boolean;
{secondary}
Function DeleteConnectionsDriveMappings(ConnId:Byte):Boolean;
{secondary}
Function IsSearchDrive(DriveNumber:byte):boolean;
{4409 }
Function IsNetworkDrive(driveNumber:Byte):boolean;
{ isNetworkDrive is set to TRUE if the drive is a) a network drive, and
b) a legal drive letter was used. }
{------------------------- entries -----------------------------------------}
{F217/0F [2.15c+]}
Function ScanFileInformation(DirHandle:Byte; FilePath:string;
SearchAttrib:Byte;
{i/o} VAR SequenceNbr:Integer;
{out} VAR fileInfo:Tentry):Boolean;
{F217/F4 [3.0+]}
Function ConvertPathToDirEntryId(dirHandle:Byte; dirPath:string;
Var VolNbr :byte;
Var dirEntryID:LongInt):boolean;
{ aka ConvertPathToDirEntry / requires console rights }
{F216/02}
Function ScanDirectoryInformation(dirHandle:byte; searchDirPath:string;
{i/o} Var sequenceNumber:word;
{out:} Var dirInfo:Tentry ):boolean;
{F216/1F [2.15c+]}
Function GetDirectoryEntry(DirHandle:byte;
Var dirEntry:Tentry):boolean;
{F216/1E [2.15c+]}
Function ScanDirectoryEntry(DirHandle:Byte; EntryName:string; SearchFlags:Longint;
{i/o} Var EntryId:Longint;
{out} Var Entry:Tentry ):boolean;
{F217/F3 [3.0+]}
Function MapDirEntryIdToPath(VolNbr:byte;DirEntryId:Longint; NStype:byte;
Var ExtPath:string):boolean;
{F216/25 [2.15c+] }
Function SetEntry(DirHandle:Byte;EntryId:Longint;SearchFlags:Byte;
ModFlags:Longint; Entry:Tentry ):boolean;
{F217/10 [2.15c+]}
Function SetFileInformation(DirHandle:Byte; FilePath:string;
SearchAttrib:Byte;
fileInfo:TEntry):boolean;
{F216/1B [2.15c+]}
Function ScanSalvagableFiles(DirHandle:Byte;
{i/o} Var EntryId:Longint;
{out} Var Entry:Tentry ):boolean;
{F216/1D [3.0+]}
Function PurgeSalvagableFile(DirHandle:Byte;
EntryId:Longint; FileName:string):boolean;
{F216/1C [3.0+] }
Function RecoverSalvagableFile(dirHandle:Byte; EntryId:Longint;
OldName,NewName:string):boolean;
{F244 [2.1x/3.x]}
Function EraseFiles(dirHandle, searchAttrib:Byte; filePath:string ):boolean;
{60.. (extended DOS call)}
Function GetTrueEntryName(DirPath:string; Var CanonicalPath:string):boolean;
{F216/0F [2.0/2.1/3.x]}
Function RenameDirectory( dirHandle:Byte; dirPath, newDirName :String):Boolean;
{F216/0B [2.15c+]}
Function DeleteDirectory(DirHandle:Byte; DirPath:string):boolean;
{F216/0A [2.15+]}
Function CreateDirectory(DirHandle:Byte; DirPath:string; MaxRightsMask:byte):boolean;
{3B.. }
Function ChangeDirectory(DirPath:string):boolean;
{F216/24 [3.0+]}
Function SetDirRestriction(DirHandle:Byte; DiskSpaceLimit:Longint):boolean;
{F216/23 [3.0+]}
Function ScanDirRestrictions(DirHandle:Byte;
Var NumberOfEntries:Byte;
Var RestrInfo:TdirRestrList):boolean;
{--------------------------- Rights/trustees ---------------------------}
{F216/27 [3.0+]}
Function SetTrustee(DirHandle:Byte;DirPath:string;
TrusteeObjectID:Longint;
RightsMask:Word ):boolean;
{F216/2B [3.0+]}
Function DeleteTrustee(DirHandle:Byte;DirPath:String;
TrusteeObjectId:Longint):boolean;
{F216/2A [3.0+]}
function GetEffectiveRights(DirHandle:Byte;DirPath:String;
var Rights:Word) : Boolean;
{F216/04 [2.15c+]}
Function ModifyMaximumRightsMask(DirHandle:Byte;DirPath:string;
RevokeRightsMask,GrantRightsMask:Word):boolean;
{F217/47 [2.15c+]}
Function ScanBinderyObjectTrusteePaths(TrusteeObjectId:Longint;
VolumeNumber:Byte;
{i/o} Var SequenceNumber:word;
{out} Var AccessMask:Word;
Var Path:string ):boolean;
{F216/26 [3.0+]}
Function ScanEntryForTrustees(DirHandle:Byte;DirPath:String;
{i/o} Var SequenceNumber:Byte;
{out} Var TrusteeInfo: TtrusteeInformation):boolean;
IMPLEMENTATION{============================================================}
{$IFDEF MSDOS}
uses dos; { file handles / 'normal' file attributes }
{$ENDIF}
Type TintEntry=record { Unit internal Entry type }
{ 0} _res1 :Longint; { low word = Dir Id of parent Dir }
{ 4} _attrib :Longint;
{ 8} _res2 :word;
{ 10} _NStype :Byte;
{ 11} _name :string[12];
{ 24} _creationTime :Longint;
{ 28} _OwnerId :Longint; { hi-lo}
{ 32} _ArchiveTime :Longint;
{ 36} _ArchiverId :Longint; { hi-lo}
{ 40} _modifyTime :Longint;
{ 44} _ModifierId :Longint; { files only }
{ 48} _ForkSize :Longint; { files only }
{ 52} _res3 :array[1..44] of byte; { Trustee obj IDs and Tr. rights }
{ 96} _FileRightsMask:word; { files only }
{ 98} _AccessDate :word; { files only }
{100} _DirRightsMask :word; { directories only }
{102} _res4 :word; {Unique Dir ID, hi-lo} { directories only }
{104} _DeleteTime :Longint; { salvageable files only }
{108} _DeletorID :LongInt; { salvageable files only }
{112} _res5 :array[1..16] of byte;
{128} end;
Procedure Convert2ExtEntry(Var Ie:TintEntry;Var Oe:Tentry);
begin
FillChar(Oe,Sizeof(Tentry),#$0);
with Ie,Oe
do begin
Attributes:=_Attrib;
NStype:=_NStype;
Entryname:=_name;
DosTime2NovTime(_CreationTime,CreationTime);
OwnerId:=Lswap(_OwnerId); {force lo-hi}
DosTime2NovTime(_ArchiveTime,ArchiveTime);
ArchiverId:=Lswap(_ArchiverID); {force lo-hi}
DosTime2NovTime(_ModifyTime,ModifyTime);
if (_attrib and $10)>0 { is entry a directory ? }
then begin
RightsMask:=_DirRightsMask;
end
else begin
ModifierId:=LSwap(_ModifierId); {force lo-hi}
DataForksize:=_Forksize;
if _NSType=0
then FileSize:=_ForkSize;
RightsMask:=_FileRightsMask;
DosTime2NovTime(MakeLong(_accessDate,0),LastAccessTime);
DosTime2NovTime(_DeleteTime,DeleteTime);
DeletorId:=Lswap(_DeletorID); {force lo-hi}
end;
end;
end;
Procedure Convert2IntEntry(Var Oe:TEntry;Var Ie:TIntEntry);
Var TempTime:Longint;
begin
FillChar(Ie,Sizeof(Tentry),#$0);
with Ie,Oe
do begin
_Attrib:=Attributes;
_NStype:=NStype;
_Name:=EntryName;
NovTime2DosTime(CreationTime,_CreationTime);
_OwnerId:=Lswap(OwnerId); {force hi-lo}
NovTime2DosTime(ArchiveTime,_ArchiveTime);
_ArchiverId:=Lswap(ArchiverId); {force hi-lo}
NovTime2DosTime(ModifyTime,_ModifyTime);
if (Attributes and $10)>0 { is entry a directory ? }
then begin
_DirRightsMask:=RightsMask;
end
else begin
_ModifierId:=Lswap(ModifierId); { force hi-lo }
_ForkSize:=DataForkSize;
_FileRightsMask:=RightsMask;
NovTime2DosTime(LastAccessTime,TempTime);
_AccessDate:=HiLong(TempTime);
NovTime2DosTime(DeleteTime,_DeleteTime);
_DeletorID:=Lswap(DeletorId); { force hi-lo }
end;
end;
end;
Procedure ConvertPathToVolFormat(Var path:string);
{ reformat \\server\vol\path to VOL:PATH
server/vol:path to VOL:PATH }
Var pcolon,pslash:byte;
begin
if (Path[0]>#1) and (Path[1]='\') and (Path[2]='\')
then begin
delete(Path,1,2);
Path:=Path+'\';
pslash:=pos('\',Path);
if pslash>0
then begin
delete(Path,1,pslash); { remove servername from path }
pslash:=pos('\',Path);
if pslash>0
then Path:=copy(Path,1,pslash-1)+':'+copy(Path,pslash+1,255);
end;
while Path[ord(Path[0])]='\' do dec(Path[0]);
end
else begin
pcolon:=pos(':',path);
if (path[0]>#3) and (pcolon>3)
then begin
pslash:=pos('/',path);
if (pslash=0) or (pslash>pcolon)
then pslash:=pos('\',path);
if (pslash>0) and (pslash<pcolon)
then delete(path,1,pslash); { remove 'server/' }
end;
end;
end;
{------------------ Volume Management --------------------------------------}
{F216/2C [2.15c+]}
Function GetVolumeUsage(VolumeNumber:byte; Var VolUsage: TvolUsage):boolean;
Type Treq=record
len:word;
subf:byte;
volNbr:byte;
end;
Trep=TvolUsage;
TPreq=^Treq;
TPrep=^Trep;
begin
with TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subf:=$2C;
volNbr:=VolumeNumber;
end;
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
VolUsage:=TPrep(GlobalReplyBuf)^;
IF (Volusage.totalBlocks=0)
or (volusage.volumename='')
then result:=$98;
GetVolumeUsage:=(result=0);
{resultcodes:
00 success; 98h Volume doesn't exist / not mounted }
end;
{F216/06 [2.15c+]}
Function GetVolumeName(volumeNumber:Byte; Var volumeName:String ):boolean;
{ Returns the volume name of a give volume number [0..31].
If the volume name doesn't exist, or the volume is not mounted
at the time of this call, an error $98 results and volName is set to '' }
Type Treq=record
len :word;
subFunc :byte;
volNbr :Byte;
end;
Trep=record
_volName:String[16];
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$06;
volNbr:=volumeNumber
end;
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
volumeName:=TPrep(GlobalReplyBuf)^._volName;
if volumeName=''
then result:=$98;
GetVolumeName:=(result=0)
{resultcodes:
00 success; 98h Volume doesn't exist / not mounted }
end;
{F216/05 [2.15c+]}
Function GetVolumeNumber( volumeName:String; Var volumeNumber:Byte ):boolean;
{ Returns the volume number [0..31] of a given volume name.
The volumename can have a maximum of 16 characters. Wildcards are
allowed, the volume number of the first match will be returned.
The name of the volume may be supplied with ('SYS:') or without
the colon ('SYS'). }
Type Treq=record
len :word;
subFunc :byte;
volName :String[16];
end;
Trep=record
volNbr :Byte;
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$05;
if volumeName[0]>#16
then volumeName[0]:=#16;
volName:=volumeName;
if volname[ord(volName[0])]=':'
then dec(volName[0]);
len:=2+ord(volName[0]);
F2SystemCall($16,len+2,SizeOf(Trep),result);
end;
volumenumber:=TPrep(GlobalReplyBuf)^.volNbr;
getVolumeNumber:=(result=0)
{resultcodes:
00 success; 98h volume doesn't exist }
end;
{F216/15 [2.15c+]}
Function GetVolumeNameWithHandle( dirHandle:Byte;
Var volumeName:String ):boolean;
Type Treq=record
len :word;
subFunc :byte;
_dirHandle :Byte;
end;
Trep=record
_sectPerBlock :Word; {hi-lo}
_TotalBlocks :Word; {hi-lo}
_availBlocks :Word; {hi-lo} { Use GetVolumeUsage for the other fields }
_TotalDirSlots:Word; {hi-lo}
_availDirSlots:Word; {hi-lo}
_volName :array[1..16] of byte;
_volRemoveable:Word; {hi-lo}
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$15;
_dirHandle:=dirHandle;
end;
F2SystemCall($16,Sizeof(Treq),SizeOf(Trep),result);
ZStrCopy(volumeName,TPrep(GlobalReplyBuf)^._volName,16);
if volumeName=''
then result:=$9B; { Invalid directory handle }
getVolumeNameWithHandle:=(result=0)
{ resultcodes: 00 success; $9B invalid directory handle }
end;
{F212 [2.15c+]}
Function IsVolumeRemovable( volumeNumber:Byte;
Var volIsRemoveable:Boolean):boolean;
{ stripped down version of the GetVolumeInfoWithNumber call }
Type Treq=Byte;
Trep=record
_sectPerBlock :Word; {hi-lo}
_TotalBlocks :Word; {hi-lo}
_availBlocks :Word; {hi-lo}
_TotalDirSlots :Word; {hi-lo}
_availDirSlots :Word; {hi-lo}
_volName :array[1..16] of byte;
_volRemoveable :Word; {hi-lo}
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
TPreq(GlobalReqBuf)^:=volumeNumber;
F2SystemCall($12,SizeOf(Treq),SizeOf(Trep),result);
With TPrep(GlobalReplyBuf)^
do begin
volIsRemoveable:=(_volRemoveable>0);
if _volName[1]=0
then result:=$98;
end;
IsVolumeRemovable:=(result=0);
{ resultcodes: 00 success; 98h Invalid volume number / volume not mounted }
end;
{F216/22 [3.x]}
Function ClearObjectVolRestriction(VolumeNumber:byte; objId:LongInt):boolean;
{ If the objId doesn't exist, no error is returned. }
Type Treq=record
len:word;
subFunc:byte;
_volNbr:byte;
_objId:LongInt; { hi-lo }
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$22;
_volNbr:=VolumeNumber;
_objId:=Lswap(objId); { force hi-lo }
end;
F2SystemCall($16,SizeOf(Treq),0,result);
ClearObjectVolRestriction:=(result=0)
{ $8C No supervisor rights }
end;
{F216/29 [3.x]}
Function GetObjectVolRestriction(VolumeNumber:byte; objId:LongInt;
Var MaxAllowedBlocks,BlocksInUse:LongInt):boolean;
{ If MaxAllowedBlocks is equal to $40000000 on return, there are no
disk restrictions for the object on this volume. }
{ You need not be logged in to use this call. }
Type Treq=record
len :word;
subFunc:byte;
_volNbr:byte;
_objId :Longint; {hi-lo}
end;
Trep=record
_MaxAllowedBlocks,
_BlocksInUse :Longint;
end;
TPreq=^Treq;
TPrep=^Trep;
Var objName:string;
objType:word;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len :=SizeOf(Treq)-2;
subFunc:=$29;
_volNbr:=VolumeNumber;
_objId :=Lswap(objId); {force hi-lo}
end;
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
With TPrep(GlobalReplyBuf)^
do begin
MaxAllowedBlocks:=_MaxAllowedBlocks;
BlocksInUse:=_BlocksInUse;
If BlocksInUse=0
then if NOT nwBindry.GetBinderyObjectName(objId,objName,objType)
then result:=$FF;
end;
GetObjectVolRestriction:=(result=0)
{resultcodes: 00 success; $FF Invalid objectId }
end;
{F216/20 [3.x]}
Function ScanVolForRestrictions(VolumeNumber:byte;
{i/o} Var sequenceNbr:LongInt;
{out} Var NbrOfObjects:byte;
Var ResultBuffer:TobjVolRestr):boolean;
{ 1st call: sequenceNbr=0,
// n-th call: sequenceNbr(n):=sequenceNbr(n-1)+NbrOfObjects
// (addition done by function itself)
after last call: sequenceNbr=0 again. }
Type Treq=record
len:word;
subFunc:byte;
_volNbr:byte;
_seqNbr:LongInt; { lo-hi !}
end;
Trep=record
_NbrOfObjects:byte;
_buff :TobjVolRestr;
end;
TPreq=^Treq;
TPrep=^Trep;
Var t:byte;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$20;
_volNbr:=VolumeNumber;
_seqNbr:=sequenceNbr;
end;
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
if result=0
then begin
With TPrep(GlobalReplyBuf)^
do begin
NbrOfObjects:=_NbrOfObjects;
ResultBuffer:=_buff;
For t:=1 to NbrOfObjects
do ResultBuffer[t].objId:=Lswap(_buff[t].ObjId);
if _NbrOfObjects=0
then result:=$FF
else sequenceNbr:=sequenceNbr+_NbrOfObjects;
end
end
else NbrOfObjects:=0;
ScanVolForRestrictions:=(result=0)
{ $98 VolumeNumber doesn't exist;
$FF No New restriction data (end of iteration) }
end;
{F216/21 [3.x]}
Function SetObjectVolRestriction(VolumeNumber:byte; objId,MaxAllowedBlocks:LongInt):boolean;
{ If the objId doesn't exist, no error is returned. }
Type Treq=record
len :word;
subFunc:byte;
_volNbr:byte;
_objId :Longint; {hi-lo}
_maxBlocks:LongInt; {lo-hi !!}
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalreqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$21;
_volNbr:=VolumeNumber;
_objId:=Lswap(objId); { force hi-lo }
_maxBlocks:=MaxAllowedBlocks;
end;
F2SystemCall($16,SizeOf(Treq),0,result);
SetObjectVolRestriction:=(result=0)
{ $8C No supervisor Rights }
end;
{--------------Dir handles/ drive mappings----------------------------------}
{BA.. }
Function GetEnvPath(Var EnvPath:string):boolean; {#d}
Type Tarr=array[1..2048] of byte;
Var regs:TTregisters;
penv:^Tarr;
i,envSize:word;
state:byte;
begin
regs.ah:=$BA;
RealModeIntr($21,regs);
envSize:=byte(nwPtr(regs.dx-1,3)^) SHL 4;
penv:=nwPtr(regs.dx,0);
i:=1;
state:=0;
while (i<envSize) and (state<5)
do begin
CASE state of
4:if penv^[i]=ord('=')
then state:=5
else state:=0;
3:if penv^[i]=ord('H')
then state:=4
else state:=0;
2:if penv^[i]=ord('T')
then state:=3
else state:=0;
1:if penv^[i]=ord('A')
then state:=2
else state:=0;
0:if penv^[i]=ord('P')
then state:=1;
end; {case}
inc(i);
end;
if state<5
then begin
result:=$300;
GetEnvPath:=false;
exit;
end;
EnvPath:='';
while (i<=envSize) and (penv^[i]<>0)
do begin
EnvPath:=EnvPath+chr(penv^[i]);
inc(i);
end;
if i>envSize
then begin
result:=$301;
GetEnvPath:=false;
exit;
end;
result:=0;
GetEnvPath:=true;
{ 00 successful
300 'Path' not found
301 Path value could not be read }
end;
{BA.. }
Function SetEnvPath(EnvPath:string):boolean; {#d}
Type Tarr=array[1..2048] of byte;
Var regs:TTregisters;
penv:^Tarr;
i,t,envSize:word;
state:byte;
pbegin,pend:word;
NewPathSize,OldPathSize:byte;
diff:integer;
sVector:TsearchDriveVector;
Vecind,p:byte;
dn:Byte;
begin
Upstring(EnvPath);
If pos('PATH=',envPath)=1
then delete(EnvPath,1,5);
regs.ah:=$BA;
RealModeIntr($21,regs);
envSize:=word(nwPtr(regs.dx-1,3)^) SHL 4;
penv:=nwPtr(regs.dx,0);
i:=1;
state:=0;
while (i<envSize) and (state<5)
do begin
CASE state of
0:if penv^[i]=ord('P')
then state:=1;
1:if penv^[i]=ord('A')
then state:=2
else state:=0;
2:if penv^[i]=ord('T')
then state:=3
else state:=0;
3:if penv^[i]=ord('H')
then state:=4
else state:=0;
4:if penv^[i]=ord('=')
then state:=5
else state:=0;
end; {case}
inc(i);
end;
if state<5
then begin
result:=$300;
SetEnvPath:=false;
exit;
end;
{ determine starting and ending character of path variable }
pbegin:=i;
while (i<envSize) and (penv^[i]<>0)
do inc(i);
if i>envSize
then begin
result:=$301;
SetEnvPath:=false;
exit;
end;
dec(i);
pend:=i;
{ determine end of 'active' environment / marked by $00 00}
while (i<envSize) and NOT ((penv^[i]=0) and (penv^[i+1]=0))
do inc(i);
if i=envSize
then begin
result:=$301;
SetEnvPath:=false;
exit;
end;
inc(i); { penv^[i] = 'second' 00, end-of-environment }
OldPathSize:=1+pend-pbegin;
NewPathSize:=ord(EnvPath[0]);
If (i+NewPathSize-OldPathSize)>envSize
then begin
result:=$302;
SetEnvPath:=false;
exit;
end;
diff:=NewPathSize-OldPathSize;
if diff>0
then for t:=i downto pend
do penv^[t+diff]:=penv^[t];
if diff<0
then for t:=pend to i
do penv^[t+diff]:=penv^[t];
Move(EnvPath[1],penv^[pbegin],NewPathSize);
FillChar(Svector,SizeOf(TsearchDriveVector),#$FF);
VecInd:=1;
REPEAT
p:=pos(':',envPath);
if p>0
then begin
dn:=ord(ord(envPath[p-1])-ord('A'));
p:=pos(';',envPath);
if p=0
then envPath:=''
else delete(envPath,1,p);
IF IsNetworkDrive(dn)
then begin
Svector[VecInd]:=dn;
inc(VecInd)
end;
end;
UNTIL (p=0) or (VecInd=17);
SetSearchDriveVector(Svector);
result:=0;
SetEnvPath:=true;
{ 00 successful
300 'Path' not found
301 Environment failure
302 Environment overflow (new path too large) }
end;
{F216/01}
Function GetDirectoryPath(DirHandle:byte; Var PathName:string):boolean;
{ path includes volumename }
Type Treq=record
len :word;
subFunc:byte;
_dh :byte;
end;
Trep=record
DirPath:string[255];
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$01;
_dh:=DirHandle;
end;
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
PathName:=TPrep(GlobalReplyBuf)^.DirPath;
GetDirectoryPath:=(result=0)
{ 00 Successful 9B Bad directory handle }
end;
{EF02 [2.0/2.1/3.x]}
Function GetDriveConnectionID( DriveNumber:Byte; Var connID:Byte):boolean;
{ returns the servernumber (1..8) associated with a drive. }
Type pArr=^arr;
arr=array[0..31] of byte;
Var regs:TTregisters;
begin
regs.ax:=$EF02;
RealModeIntr($21,Regs);
If DriveNumber>31
then result:=$0105
else begin
connID:=Parr(nwPtr(Regs.es,regs.si))^[DriveNumber];
Result:=0;
end;
GetDriveConnectionID:=(Result=0);
end;
{EF02 [2.0/2.1/3.x]}
Function SetDriveConnectionID( DriveNumber:Byte; connID:Byte):boolean;
Type pArr=^arr;
arr=array[0..31] of byte;
Var regs:TTregisters;
begin
regs.ax:=$EF02;
RealModeIntr($21,Regs);
If DriveNumber>31
then result:=$0105
else begin
Parr(nwPtr(Regs.es,regs.si))^[DriveNumber]:=connId;
Result:=0;
end;
SetDriveConnectionID:=(Result=0);
end;
{EF00 [2.0/2.1/3.x]}
Function GetDriveHandle( DriveNumber:Byte; Var DirHandle:Byte ):boolean;
{ The call returns a pointer to the shell's Drive Handle Table. (32 bytes)
(Drives A..Z and temporary drives [\]^_' )
If a drive has been assigned a directory handle on the file server,
the handle can be found in the DHT at the position corresponding with the drive letter.}
Type pArr=^arr;
arr=array[0..31] of byte;
Var regs:TTregisters;
begin
regs.ax:=$EF00;
RealModeIntr($21,regs);
if DriveNumber>31
then result:=$0105
else begin
DirHandle:=Parr(nwPtr(Regs.Es,Regs.Si))^[DriveNumber];
Result:=0;
end;
GetDriveHandle:=(Result=0);
end;
{EF00 [2.0/2.1/3.x]}
Function SetDriveHandle( DriveNumber:Byte; DirHandle:Byte ):boolean;
Type pArr=^arr;
arr=array[0..31] of byte;
Var regs:TTregisters;
begin
regs.ax:=$EF00;
RealModeIntr($21,regs);
if DriveNumber>31
then result:=$0105
else begin
Parr(nwPtr(Regs.Es,Regs.Si))^[DriveNumber]:=DirHandle;
Result:=0;
end;
SetDriveHandle:=(Result=0);
end;
{EF01 [2.0/2.1/3.x]}
Function GetDriveFlag( DriveNumber:Byte; Var DriveStatus:Byte ):Boolean;
{ This call returns a pointer to the shell's Drive Flag Table (32 Bytes)
Each entry indicates a drive's status (permanent,temporary,local,unassigned)
For further explanation see the DRIVE_xxx constants.}
Type pArr=^arr;
arr=array[0..31] of byte;
Var regs:TTregisters;
begin
regs.ax:=$EF01;
RealModeIntr($21,Regs);
If DriveNumber>31
then result:=$0105
else begin
DriveStatus:=Parr(nwPtr(Regs.es,regs.si))^[DriveNumber];
Result:=0;
end;
GetDriveFlag:=(Result=0);
end;
{EF01 [2.0/2.1/3.x]}
Function SetDriveFlag( DriveNumber:Byte; DriveStatus:Byte ):Boolean;
Type pArr=^arr;
arr=array[0..31] of byte;
Var regs:TTregisters;
begin
regs.ax:=$EF01;
RealModeIntr($21,Regs);
If DriveNumber>31
then result:=$0105
else begin
Parr(nwPtr(Regs.es,regs.si))^[DriveNumber]:=DriveStatus;
Result:=0;
end;
SetDriveFlag:=(Result=0);
end;
{E900 [2.0/2.1/3.x]}
Function GetDirectoryHandle( DriveNumber:Byte; Var dirHandle,status:byte):Boolean;
{ Returns directory handle and status flags for a drive. }
{ Drivenumber = 0..31 (A..Z = 0..25) and temp drives (26..31) }
{ Status Byte
7 6 5 4 3 2 1 0
| | +-Permenant Directory Handle
| +----Temporary Directory Handle
+----------------------Mapped to a local drive }
{ in case of an invalid driveNumber, handle and status will be set to 0 }
Var Regs:TTRegisters;
begin
With Regs
do begin
AX:=$E900;
DX:=DriveNumber;
RealModeIntr($21,Regs);
{ AH = Status Flags;
01 mapped to a permanent dir handle;
02 mapped to a temporary dir handle;
80 local drive. }
dirHandle:=AL;
status:=AH;
If dirHandle=0
then begin status:=0;Result:=$FF end {INVALID_DRIVE_NUMBER}
else Result:=0;
GetDirectoryHandle:=(Result=0)
end;
{ result: $00 success; $FF Invalid Drive Number }
end;
{F216/00 [2.15c+]}
Function SetDirectoryHandle( sourceDirHandle:Byte; sourceDirPath:String;
targetDirHandle:Byte ):boolean;
{ make handle 'targetHandle' point to the directory provided by
sourceHandle and/or sourceDirPath. ( "Volume:dir\subdir" ) }
Type Treq=record
len :word;
subFunc :byte;
_TargetDH :Byte;
_SourceDH :Byte;
_SourceDP :String[255]
end;
TPreq=^Treq;
Var p:Byte;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$00;
_TargetDH:=targetDirHandle;
_SourceDH:=SourceDirHandle;
if SourceDirHandle=0
then ConvertPathToVolFormat(SourceDirPath);
_sourceDP:=sourceDirPath;
UpString(_sourceDP);
len:=4+ord(_SourceDP[0]);
F2SystemCall($16,len+2,0,result);
end;
SetDirectoryHandle:=(result=0)
{ resultcodes:
00 Success; 98h Volume does not exist;
9Bh Bad directory handle; 9Ch Invalid Path. }
end;
{F216/12 [2.15c+]}
FUNCTION AllocPermanentDirHandle( DriveNumber:Byte;
DirHandle : byte; DirPath : string ;
var NewDirHandle, EffectiveRights: byte ) :boolean;
{ Effective server must be the server involved, i.e. where the dir is stored }
Type Treq=record
len : word;
subf : byte;
_dirHandle : byte;
_driveLetter : char;
_DirectoryPath: String[255];
end;
Trep=record
_newDirHandle : byte;
_EffectiveRights : byte; { e.r. mask }
end;
TPreq=^Treq;
TPrep=^Trep;
Var p:Byte;
BEGIN
With TPreq(GlobalReqBuf)^
do begin
subf := $12;
_dirHandle := dirHandle;
_driveLetter := chr(DriveNumber+ord('A'));
if Dirhandle=0
then ConvertPathToVolFormat(DirPath);
_DirectoryPath:=DirPath;
UpString(_DirectoryPath);
len:=4+ord(_DirectoryPath[0]);
F2SystemCall($16,len+2,sizeof(Trep),result);
end;
if result = 0
then with TPrep(GlobalReplyBuf)^
do begin
effectiveRights := _effectiveRights;
newDirHandle := _newDirHandle;
end;
AllocPermanentDirHandle:=(result=0);
{ $00 Successful $98 Volume doen't exist $9C Invalid path }
end;
{F216/13 [2.15c+]}
function AllocTemporaryDirHandle( DriveNumber:byte;
DirHandle : Byte; DirPath : String;
var NewDirHandle,EffectiveRights : Byte) : Boolean;
{ Allocates a temporary directory handle, deleted automatically by EOJ. }
{ Effective server must be the server involved, i.e. where the dir is stored }
Type TReq=record
Len : Word;
SubF : Byte;
Handle : Byte;
Letter : Char;
_DirectoryPath : String;
end;
TRep=record
NewH : Byte;
Mask : Byte;
end;
TPreq=^Treq;
TPrep=^Trep;
Var p:Byte;
begin
with TPReq(GlobalReqBuf)^
do begin
SubF := $13;
Handle := DirHandle;
Letter := chr(DriveNumber+ord('A'));
{ Allocating handles requires paths to be in
the VOL:path format.. NOT canonical }
if handle=0
then ConvertPathToVolFormat(DirPath);
_DirectoryPath:=DirPath;
UpString(_DirectoryPath);
Len:=4+length(_DirectoryPath);
F2SystemCall($16,len+2,SizeOf(Trep),result);
end;
with TPrep(GlobalReplyBuf)^
do begin
NewDirHandle := NewH;
EffectiveRights := Mask;
end;
AllocTemporaryDirHandle:=(result=0);
{ result: 00 success; 98h Volume doesn't exist; 9Ch Invalid Path }
end;
{F216/14 [2.15c+]}
function DeallocateDirHandle(DirHandle : Byte) : Boolean;
{ This function deletes a directory handle }
Type TReq=record
Len : Word;
SubF : Byte;
Handle : Byte;
end;
TPreq=^Treq;
begin
with TPReq(GlobalReqBuf)^
do begin
Len := 2;
SubF := $14;
Handle:= DirHandle;
end;
F2SystemCall($16,Sizeof(Treq),0,result);
DeallocateDirHandle:=(result=0);
{ result:
00h - Success; 9Bh - Bad directory handle }
end;
{E901 }
Function GetSearchDriveVector(Var vector:TsearchDriveVector):boolean;
Var regs:TTregisters;
tmp1,tmp2:word;
begin
regs.ax:=$E901;
GetGlobalBufferAddress(tmp1,tmp2,regs.ds,regs.dx);
{ DS:DX real-mode address of GlobalReplyBuffer }
RealModeIntr($21,regs);
result:=0;
Move(GlobalReplyBuf^,vector,sizeof(TsearchDriveVector));
vector[17]:=$FF;
GetSearchDriveVector:=True;
end;
{E902 }
Function SetSearchDriveVector(vector:TsearchDriveVector):boolean;
Var regs:TTregisters;
tmp1,tmp2:word;
begin
regs.ax:=$E902;
Move(vector,GlobalReqBuf^,sizeof(TsearchDriveVector));
GetGlobalBufferAddress(regs.ds,regs.dx,tmp1,tmp2);
{ DS:DX real-mode address of GlobalRequestBuffer }
RealModeIntr($21,regs);
result:=0;
SetSearchDriveVector:=True;
end;
Function IsSearchDrive(DriveNumber:byte):boolean;
Var pth:string;
begin
IsSearchDrive:=(getEnvPath(pth)
and (pos(chr(DriveNumber+ord('A'))+':',pth)>0));
end;
{E905 (shell 3.00+)}
Function MapFakeRootDirectory(DriveNumber:byte; DirPath:string):boolean;
{ Dirpath may include server and volumename }
Var regs:TTregisters;
tmp1,tmp2:word;
PName:string;
begin
with regs
do begin
ax:=$E905;
bl:=driveNumber+1; { FF default, 0=A, 2= B etc. }
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
{ VLM patch for SERVER/VOL: and VOL: type paths }
if (DirPath[0]>#2) and (pos(':',DirPath)>2)
then GetTrueEntryName(DirPath,PName)
else PName:=DirPath;
Pname:=Pname+#0;
move(PName[1],GlobalReqBuf^,ord(PName[1]));
{ DS:DX real-mode address of GlobalRequestBuffer holding new path }
RealModeIntr($21,regs);
if (flags and 1 {carry})>0
then result:=al
else result:=0;
end;
MapFakeRootDirectory:=(result=0);
{ $00 Successful $03 Invalid path $0F Invalid Drive $11 Not same device }
end;
{E906 (shell 3.00+)}
Function DeleteFakeRootDirectory(DriveNumber:byte):boolean;
Var regs:TTregisters;
begin
with regs
do begin
ax:=$E906;
bl:=DriveNumber+1;
RealModeIntr($21,regs);
result:=0;
end;
DeleteFakeRootDirectory:=(result=0);
end;
{E907 (shell 3.00+)}
Function GetRelativeDriveDepth(DriveNumber:byte; Var depth:byte):boolean;
Var regs:TTregisters;
begin
with regs
do begin
ax:=$E907;
bl:=DriveNumber+1;
RealModeIntr($21,regs);
depth:=al;
if al<$FF
then result:=0
else result:=$FF; { no fake root assigned }
end;
GetRelativeDriveDepth:=(result=0);
{ 00 Succesful $FF No fake root assigned }
end;
{secondary}
Function DeleteDriveMapping(DriveNumber:Byte):boolean;
Var dirHandle,status:byte;
pth:string;
ch:char;
p:byte;
DDepth,Dflag:byte;
begin
{ if searchdrive, remove drive from searchtable and PATH environment string }
IF GetEnvPath(pth)
then begin
if pth[ord(pth[0])]<>';'
then pth:=pth+';';
p:=pos(chr(DriveNumber+ord('A'))+':',pth);
if p>0
then begin { it is a searchdrive, remove from path }
Repeat
ch:=pth[p];
delete(pth,p,1);
UNTIL ch=';';
SetEnvPath(pth); { also creates a new searchdriveVector }
end;
end;
IF (result=0) and GetDirectoryHandle(DriveNumber,dirHandle,status)
then begin
IF GetRelativeDriveDepth(DriveNumber,DDepth) { is it a fake root ? }
then DeleteFakeRootDirectory(DriveNumber);
GetDriveFlag(DriveNumber,Dflag);
SetDriveFlag(DriveNumber,(Dflag and $F0) or DRIVE_UNUSED);
SetDriveHandle(DriveNumber,0);
SetDriveConnectionId(DriveNumber,0);
DeallocateDirHandle(dirHandle);
end;
DeleteDriveMapping:=(result=0);
end;
{secondary }
FUNCTION MapPermanentDrive(DriveNumber:byte; DirectoryPath:string;
Root:boolean):boolean;
var pth : string;
DriveHandle: Byte;
begin
IF GetTrueEntryName(DirectoryPath,pth)
then begin
while pth[ord(pth[0])] IN ['\','.','*','?']
do dec(pth[0]);
if pth[1]<>'\'
then result:=$104 { attempt to map network drive to local drive }
else begin
If GetDriveHandle(DriveNumber,DriveHandle) and (DriveHandle<>0)
then DeleteDriveMapping(DriveNumber);
IF MapFakeRootDirectory(DriveNumber,pth)
then begin
if (not root)
then DeleteFakeRootDirectory(DriveNumber);
{ does not delete the mapping itself,
only the fake root. }
end;
end;
end
else result:=$101; { direcory not locatable }
MapPermanentDrive:=(result=0);
end;
{secondary}
FUNCTION MapDrive(DriveNumber:Byte; DirectoryPath:string;
Root, Permanent:boolean):boolean;
var rights : byte;
newHandle : byte;
HandlePth,pth,srvr,vol: string;
OldConnId,VolConnId:byte;
p:byte;
VolNbr:byte;
Dflag:byte;
begin
IF Permanent
then begin
MapDrive:=MapPermanentDrive(DriveNumber,DirectoryPath,Root);
exit;
end;
{ map temporary drive }
IF GetTrueEntryName(DirectoryPath,pth)
then begin
if pth[ord(pth[0])]<>'\'
then pth:=pth+'\';
if pth[1]<>'\'
then result:=$104 { attempt to map network drive to local drive }
else begin
delete(pth,1,2);
p:=pos('\',pth);
if p=0 then result:=$106;
srvr:=copy(pth,1,p-1);
delete(pth,1,p);
p:=pos('\',pth);
if p=0 then result:=$105; { volume does not exist }
vol:=copy(pth,1,p-1);
delete(pth,1,p);
IF NOT GetConnectionId(srvr,VolConnId)
then result:=$106; { server does not exist }
end;
end
else result:=$101; { direcory not locatable }
if (result=0)
then begin
while pth[ord(pth[0])] IN ['\','.','*','?']
do dec(pth[0]);
{ rebuild path: Alloc handle requires VOL:path format }
HandlePth:=vol+':\'+pth;
GetPreferredConnectionId(OldConnId);
SetPreferredConnectionId(VolConnId);
{ IF Permanent
then AllocPermanentDirHandle(DriveNumber,0,HandlePth,
newHandle,rights)
else}
AllocTemporaryDirHandle(DriveNumber,0,HandlePth,
newHandle,rights);
if (result=0)
then begin
GetDriveFlag(DriveNumber,Dflag);
{If Permanent
then SetDriveFlag(DriveNumber,(Dflag and $F0) or DRIVE_PERMANENT)
else}
SetDriveFlag(DriveNumber,(Dflag and $F0) or DRIVE_TEMPORARY);
SetDriveHandle(DriveNumber,newHandle);
SetDriveConnectionId(DriveNumber,VolConnId);
IF root
then MapFakeRootDirectory(DriveNumber,'\\'+srvr+'\'+vol+'\'+pth);
end;
SetPreferredConnectionId(OldConnId);
end;
MapDrive:=(result=0);
end;
Function MapSearchDrive(DriveNumber:byte; DirPath:string;
PathPosition:byte;
Insert,Root,Permanent:Boolean):boolean;
Var pth:string;
p,scCount:byte;
ch:char;
begin
IF MapDrive(DriveNumber,DirPath,Root,Permanent)
then begin
GetEnvPath(pth);
if pth[ord(pth[0])]<>';'
then pth:=pth+';';
scCount:=1;p:=1;
while (scCount<PathPosition) and (p<=ord(pth[0]))
do begin
if pth[p]=';'
then inc(scCount);
inc(p);
end;
{ pth[p] is first character of PathPositions' entry in path }
If p<ord(pth[0])
then begin
IF (Not Insert)
then Repeat
ch:=pth[p];
delete(pth,P,1);
UNTIL (ch=';') or (p>=ord(pth[0]));
pth:=copy(pth,1,p-1)+chr(DriveNumber+ord('A'))
+':.;'+copy(pth,p,255);
end
else pth:=pth+chr(DriveNumber+ord('A'))+':.;';
SetEnvPath(pth);
end;
MapSearchDrive:=(result=0);
end;
{secondary}
Function DeleteConnectionsDriveMappings(ConnId:Byte):Boolean;
Var t,connId2,res:Byte;
begin
res:=$FF;
for t:=0 to 31
do if GetDriveConnectionId(t,connId2) and (connId2=connId)
then begin
DeleteDriveMapping(t);
if result=0
then res:=0;
end;
result:=res;
DeleteConnectionsDriveMappings:=(result=0);
{00 successful FF No mappings affected OR Invalid connectionId }
end;
{4409 / implemented as a secondary function }
Function IsNetworkDrive(driveNumber:Byte):boolean;
{ isNetworkDrive is set to TRUE if the drive is a) a network drive, and
b) a legal drive letter was used. }
Var regs:TTRegisters;
begin
With regs
do begin
AX:=$4409;
BL:=DriveNumber+1;
RealModeIntr($21,Regs);
IsNetworkDrive:=(DX and $1000)<>0
end;
end;
{--======================-- Entries --===============================--}
{60.. (extended DOS call)}
Function GetTrueEntryName(DirPath:string; Var CanonicalPath:string):boolean;
{ SERVER/VOL:[\]Path -> \\SERVER\VOL\path
VOL:[\]Path -> \\effective_server_name\VOL\path
D:\ -> D:\.
{ if a volumename is supplied without a servername, the name of the
effective server will be returned. }
{ Format of returned string:
a) D:\path\file.ext or
b) \\servername\volumename\path\file.ext }
LABEL skip;
Var reply :array[1..128] of byte;
regs :TTregisters;
pcolon,
pslash :byte;
srvr,
volname:string[47];
connId :Byte;
begin
{ ----- Pre processing }
if DirPath[0]>#2
then begin
if ((DirPath[1]='\') and (DirPath[2]='\'))
then begin
CanonicalPath:=DirPath;
UpString(Canonicalpath);
goto skip
end;
pcolon:=pos(':',DirPath);
if (pcolon=2) and (DirPath[0]=#3) and (DirPath[3]='\')
then DirPath:=DirPath+'.';
{ fix known problem of netware: D:\. instead of D:\ }
if (pcolon=2) and (DirPath[0]=#2)
then DirPath:=DirPath+'.';
{ fix know problem of -among others- OS/2-dos: D:. instead of D: }
end;
pcolon:=pos(':',DirPath);
if pcolon>2
then begin { format must be VOL:[\]path or SERVER/VOL:[\]Path }
pslash:=pos('/',DirPath);
if pslash=0
then pslash:=$FF;
if (pslash<pcolon)
then begin { SERVER/VOL: }
srvr:=copy(DirPath,1,pslash-1);
delete(DirPath,1,pslash);
pcolon:=pos(':',DirPath);
end
else begin { VOL: }
GetEffectiveConnectionId(connId);
GetFileServerName(connId,srvr);
end;
volname:=copy(dirPath,1,pcolon-1);
delete(dirPath,1,pcolon);
if (dirPath[0]>#0) and (dirPath[1]='\')
then delete(DirPath,1,1);
DirPath:='\\'+srvr+'\'+volname+'\'+DirPath;
end;
if dirPath=''
then dirPath:='\';
{ ----- actual call }
dirPath:=dirPath+#0; { zero terminate }
WITH regs
do begin
Move(dirPath[1],GlobalReqBuf^,ord(dirPath[0]));
GetGlobalBufferAddress(ds,si,es,di);
{ DS:SI real mode pointer to GlobalRequestBuffer holding asciiz path ;
ES:DI real mode pointer to GlbalReplyBuffer }
ah:=$60;
RealModeIntr($21,regs);
Move(GlobalReplyBuf^,reply[1],128);
if (regs.flags and 1 {carry})>0
then begin
result:=ax;
reply[1]:=0;
end
else result:=0;
end;
ZstrCopy(CanonicalPath,reply[1],128);
{ ----- post-processing -- strip \ and . }
skip: ;
While CanonicalPath[ord(CanonicalPath[0])] in ['\','.']
do dec(CanonicalPath[0]);
GetTrueEntryName:=(result=0);
{ $00 successful
$02 Invalid component in directory path OR drive letter only
$03 Malformed path OR invalid drive letter }
end;
{3B.. }
Function ChangeDirectory(DirPath:string):boolean;
{ does not change the default drive }
Var regs:TTregisters;
tmp1,tmp2:word;
begin
if DirPath[0]>#63
then result:=$110 { length of path too long }
else begin
DirPath:=DirPath+#0;
with regs
do begin
ah:=$3b;
Move(DirPath[1],GlobalReqBuf^,ord(DirPath[0]));
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
{ DS:DX real-mode pointer to GlobalRequestBuffer holding DirPath }
RealModeIntr($21,regs);
If (flags and 1 {carry})>0
then result:=$111 { invalid pathname }
else result:=0;
end;
end;
ChangeDirectory:=(result=0);
end;
{F216/0A [2.15+]}
Function CreateDirectory(DirHandle:Byte; DirPath:string; MaxRightsMask:byte):boolean;
Type Treq=record
len :word;
subFunc :byte;
_DirHandle:byte;
_MRM :byte;
_dirPath :string[255];
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalreqBuf)^
do begin
subFunc:=$0A;
_dirHandle:=DirHandle;
_MRM:=MaxRightsMask;
_DirPath:=DirPath;
len:=4+ord(_dirPath[0]);
F2SystemCall($16,len+2,0,result);
end;
CreateDirectory:=(result=0)
{ 00 successful 84 No create privileges 98 Volume doesn't exist
FF directory already exists }
end;
{F216/0B [2.15c+]}
Function DeleteDirectory(DirHandle:Byte; DirPath:string):boolean;
Type Treq=record
len :word;
subFunc :byte;
_DirHandle:byte;
unused :byte;
_DirPath :string[255];
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalreqBuf)^
do begin
subFunc:=$0B;
_DirHandle:=DirHandle;
_DirPath:=DirPath;
unused:=0;
len:=4+ord(_DirPath[0]);
F2SystemCall($16,len+2,0,result);
end;
DeleteDirectory:=(result=0)
{ 00 successful 8A No delete privileges
98 Volume doesn't exist 9B Bad directory handle
9C Invalid path 9F Directory in use
A0 Directory not empty }
end;
{F217/F4 [3.0+]}
Function ConvertPathToDirEntryId(dirHandle:Byte; dirPath:string;
Var VolNbr :byte;
Var dirEntryID:LongInt):boolean;
{ aka ConvertPathToDirEntry }
Type Treq=record
len :word;
subFunc :byte;
_dirHandle:byte;
_DirPath :string[255];
end;
Trep=record
_volNbr:Byte;
_EntryId:Longint; {hi-lo}
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$F4;
_dirHandle:=DirHandle;
_dirPath:=DirPath;
UpString(_DirPath);
If DirHandle=0
then ConvertPathToVolFormat(_DirPath);
len:=3+ord(_DirPath[0]);
F2SystemCall($17,len+2,SizeOf(Trep),result);
end;
With TPrep(GlobalReplyBuf)^
do begin
VolNbr :=_volNbr;
dirEntryId:=_EntryId;
end;
ConvertPathToDirEntryId:=(result=0)
{ 00 Successful 9B Bad directory Handle
9C Invalid Path C6 No console rights }
end;
{F217/F3 [3.0+]}
Function MapDirEntryIdToPath(VolNbr:byte;DirEntryId:Longint; NStype:byte;
Var ExtPath:string):boolean;
{aka MapDirectoryNumberToPath }
{ Returns full path/ with nameSpace information;
Doesn't return server or volumename. }
Type Treq=record
len :word;
subFunc :byte;
_VolNbr :byte;
_EntryId:longint; {hi-lo}
_NameSp :byte;
end;
Trep=record
_path:array[1..255] of byte; {!! maximum: 512 bytes in path ! }
end;
TPreq=^Treq;
TPrep=^Trep;
Var TempPath:string;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$F3;
_VolNbr:=VolNbr;
_EntryId:=DirEntryId;
_NameSp:=NStype;
end;
F2SystemCall($17,SizeOf(Treq),SizeOf(Trep),result);
if result=0
then begin
With TPrep(GlobalReplyBuf)^
do ZstrCopy(TempPath,_path,255);
{ TempPath according to the 'new' Novell format;
translate into a 'DOS' style path }
NovPath2DOSPath(TempPath,ExtPath); { dir\subdir (no server or volume name) }
end;
MapDirentryIdtoPath:=(result=0)
{ 00 Successful C6 No console rights FF ? }
end;
{F216/02}
Function ScanDirectoryInformation(dirHandle:byte; searchDirPath:string;
{i/o} Var sequenceNumber:word;
{out:} Var dirInfo:Tentry ):boolean;
{ set sequenceNumber to 0 before the first call.
If wildcards (* or ?) are included in the searchDirPath:
Iterate until a $9C error is returned.
If you don't include a wildcard in the searchDirPath, only use
this call once. Do not iterate, the same entry will be returned
eternaly.
}
Type Treq=record
len :word;
subFunc :byte;
_dirHandle :byte;
_subDirNumber:word; {hi-lo}
_dirPath :string[255]
end;
Trep=record
_subDirName :array[1..16] of byte;
_creationDate :word;
_creationTime :word;
_ownerObjId :LongInt; {hi-lo}
_maxRightsMask:word;
_SubDirNbr :word; {hi-lo}
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$02;
_dirHandle:=dirHandle;
_subDirNumber:=swap(sequenceNumber); { force hi-lo}
_dirPath:=searchDirPath;
UpString(_dirPath);
len:=5+ord(searchDirPath[0]);
F2SystemCall($16,len+2,SizeOf(Trep),result);
end;
With TPrep(GlobalReplyBuf)^
do begin
FillChar(dirInfo,SizeOf(Tentry),0);
ZstrCopy(dirInfo.EntryName,_SubDirName,16);
DosTime2NovTime(MakeLong(swap(_CreationDate),swap(_CreationTime)),
dirInfo.creationTime);
dirInfo.ownerId:=Lswap(_ownerObjId);
dirInfo.RightsMask:=_maxRightsMask;
sequenceNumber:=swap(_SubDirNbr)+1;
end;
ScanDirectoryInformation:=(result=0)
{resultcodes: $00 success; $98 Volume does not exist;
$9B Bad directory Handle $9C Invalid Path }
end;
{F216/0F [2.0/2.1/3.x]}
Function RenameDirectory( dirHandle:Byte; dirPath, newDirName :String):Boolean;
{ The new directory name must be a regular (legal) directory name,
max 14 chars long.
The user must have Parental and Modify rights in the parent directory of
the directory to be renamed. }
Type Treq=record
len :word;
subFunc :byte;
_dirHandle :Byte;
_dirNames :Array[0..255+1+14] of byte; { _dirpath[0] is allowed to be 0 }
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$0F;
_dirHandle:=dirHandle;
Upstring(dirPath);
UpString(newDirName);
Move(DirPath[0],_DirNames[0],ord(DirPath[0])+1);
Move(newDirName[0],_DirNames[1+_DirNames[0]],ord(newDirName[0])+1);
len:=4+ord(dirPath[0])+ord(newDirName[0]);
F2SystemCall($16,len+2,0,result);
end;
RenameDirectory:=(result=0)
{ Possible ResultCodes:
8B No Rename Privileges; 9B Bad Directory Handle;
9C Invalid Path; 9E Invalid (new) Dir Name. }
end;
{F216/1F [2.15c+]}
Function GetDirectoryEntry(DirHandle:byte;
Var dirEntry:Tentry):boolean;
Type Treq=record
len:word;
subFunc:byte;
_dirHandle:byte;
end;
Trep=record
_Entry :TintEntry;
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$1F;
_dirHandle:=dirHandle;
end;
F2SystemCall($16,SizeOf(Treq),SizeOf(Trep),result);
With TPrep(GlobalReplyBuf)^
do begin
Convert2ExtEntry(_entry,dirEntry);
end;
GetDirectoryEntry:=(result=0)
{ 00 successful 98 Volume doesn't exist
9B Bad directory handle 9C Invalid path }
end;
{B601 [2.0+] }
function SetExtendedFileAttributes(FilePath:String; Attr:Byte) : Boolean;
{ See GetExtFAttr for meaning of Attr the Attribute
Function result code:
00h Success;
FFh File not found;
FEh Access denied }
Var Novregs:TTRegisters;
tmp1,tmp2:word;
begin
with NovRegs
do begin
AX := $B601;
if FilePath[0]=#255
then FilePath[255]:=#0
else FilePath:=FilePath+#0;
Move(FilePath[1],GlobalReqBuf^,ord(FilePath[0]));
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
{ DS:DX real mode pointer to GlobalRequestBuffer holding FilePath }
CL := Attr;
RealModeIntr($21,NovRegs);
IF (Flags AND 1 {carry})>0
then Result:=AL
else Result:=$00;
Result := AL
end;
SetExtendedFileAttributes:=(Result=0);
end;
{B600 [2.0+]}
function GetExtendedFileAttributes(FilePath:String; var Attributes:Byte) : Boolean;
{ Meaning of Attributes:
7 6 5 4 3 2 1 0
| | | | | | |
| | | | +---+---+------Search mode
| | | +----------------------transactional bit A_TRANSACTIONAL
| | +--------------------------Indexing bit A_INDEXED
| +------------------------------Read Audit bit A_READ_AUDIT
+----------------------------------Write Audit bit A_WRITE_AUDIT
}
Var NovRegs:TTRegisters;
tmp1,tmp2:word;
begin
with NovRegs
do begin
AX := $B600;
if FilePath[0]=#255
then FilePath[255]:=#0
else FilePath:=FilePath+#0; { null terminate string }
Move(FilePath[1],GlobalReqBuf^,ord(FilePath[0]));
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
{ DS:DX real mode pointer to GlobalRequestBuffer hloding FilePath }
RealModeIntr($21,NovRegs);
IF (Flags and 1 {carry})>0
then Result := AL
else Result:=$00;
Attributes := CL;
end;
GetExtendedFileAttributes:=(Result=0);
{ $8C caller lacks privileges
FEh not permitted to search directory
FFh file not found }
end;
{F3.. [2.x/3.x]}
Function FileServerFileCopy( sourceFileHandle, destFileHandle:word;
sourceFileOffset, destFileOffset:Longint;
numberOfBytesToCopy :Longint;
VAR numberOfBytesCopied :Longint ):boolean;
{Note: both source and destination must be on the same file server
SeeAlso: 3C..,3F..}
Type Treq=record
_sFH,_dFH :word; {lo-hi} {as returned by GetFileHandle.}
_sFoffs,_dfOffs:Longint; {lo-hi}
_NbrOfBytes :Longint; {lo-hi}
end;
TPreq=^Treq;
Var regs:TTRegisters;
tmp1,tmp2:word;
begin
with TPreq(GlobalReqBuf)^
do begin
_sFH:=sourceFileHandle;
_dFH:=destFileHandle;
_sFoffs:=sourceFileOffset;
_dFoffs:=destFileOffset;
_NbrOfBytes:=numberOfBytesToCopy;
end;
with regs
do begin
AH:=$F3;
GetGlobalBufferAddress(es,di,tmp1,tmp2);
{ ES:DI real mode pointer to GlobalRequestBuffer }
RealModeIntr($21,regs);
result:=AL;
end;
numberOfBytesCopied:=MakeLong(regs.cx,regs.dx); { ? swap those regs for correct byte order ? }
FileServerFileCopy:=(Result=0);
end;
{level-0 function. See GetFileAttributes and SetFileAttributes }
Function DoFileAttributes(subf:byte;FilePath:string;VAR attr:byte):boolean;
Var regs:TTregisters;
tmp1,tmp2:word;
begin
with regs
do begin
AH:=$43;
AL:=subf;
if subf=$01 then CX:=attr;
if filePath[0]=#255
then filePath[255]:=#0
else filePath:=filePath+#0;
Move(FilePath[1],GlobalReqBuf^,ord(FilePath[0]));
GetGlobalBufferAddress(ds,dx,tmp1,tmp2);
{ DS:DX real mode pointer to GlobalRequestBuffer holding FilePath }
RealModeIntr($21,regs);
IF ((Flags and 1 {Fcarry})<>0)
then result:=AL
else begin
result:=$00;
if subf=$00 then attr:=CX
end;
end;
DoFileAttributes:=(result=$00);
{ resultcodes: 00 success; 01 invalid function;
03 path not found; 05 access denied. }
end;
{4300 [1.x/2.x/3.x]}
Function GetFileAttributes(FilePath:string; Var attr:byte):boolean;
{ A_READ_ONLY,A_HIDDEN,A_SYSTEM and A_SHAREABLE only. }
begin
GetFileAttributes:=DoFileAttributes($00,FilePath,attr);
end;
{4301 [1.x/2.x/3.x]}
Function SetFileAttributes(FilePath:string; attr:byte):boolean;
{ A_READ_ONLY,A_HIDDEN,A_SYSTEM and A_SHAREABLE only. }
Var _attr:byte;
begin
_attr:=attr;
SetFileAttributes:=DoFileAttributes($01,FilePath,_attr);
end;
{F217/0F [2.15c+]}
Function ScanFileInformation(DirHandle:Byte; FilePath:string;
SearchAttrib:Byte;
{i/o} VAR SequenceNbr:Integer;
{out} VAR fileInfo:Tentry):Boolean;
{ To be called Iteratatively; initial value for seqNbr=-1 }
{ wildcards in filename allowed.
Iterate util an error $FF occurs }
Type Treq=record
len :word;
subFunc :byte;
_seqNbr :word; {hi-lo}
_dirHandle :byte;
_searchAttrib:Byte;
_filePath :string;
end;
Trep=record
_seqNbr :word; {hi-lo}
_fileName :array[1..14] of byte;
_Fattr,
_ExtFattr :Byte;
_Fsize :LongInt; {hi-lo}
_Crdate :word; {hi-lo}
_LastAccDate :word; {hi-lo}
_LastUpdDate,
_LastUpdTime :Word;
_ownerObjId :Longint; {hi-lo}
_LastArchDate,
_lastArchTime:Word;
_reserved :array[1..56] of byte;
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$0F;
_seqNbr:=swap(word(SequenceNbr)); { force hi-lo }
_dirHandle:=dirHandle;
_searchAttrib:=searchAttrib;
_filePath:=FilePath;
len:=6+ord(_filePath[0]);
F2SystemCall($17,len+2,SizeOf(Trep),result);
end;
with TPrep(GlobalReplyBuf)^
do begin
FillChar(fileInfo,sizeOf(fileInfo),#0);
SequenceNbr:=Integer(swap(_seqNbr)); { force lo-hi }
ZstrCopy(fileInfo.EntryName,_filename,15);
fileInfo.Attributes:=(_ExtFattr SHL 8)+_Fattr;
fileInfo.filesize:=Lswap(_Fsize); { force lo-hi}
fileinfo.OwnerID:=Lswap(_ownerObjID); { force lo-hi}
DosTime2NovTime(MakeLong(swap(_CrDate),0),fileinfo.creationTime);
DosTime2NovTime(MakeLong(swap(_LastAccDate),0),fileinfo.lastAccessTime);
DosTime2NovTime(MakeLong(swap(_LastUpdDate),swap(_LastUpdTime))
,fileinfo.ModifyTime);
DosTime2NovTime(MakeLong(swap(_LastArchDate),swap(_lastArchTime))
,fileinfo.ArchiveTime);
end;
ScanFileInformation:=(result=0)
{ 89 No search privileges FF No more matching files }
end;
{F217/10 [2.15c+]}
Function SetFileInformation(DirHandle:Byte; FilePath:string;
SearchAttrib:Byte;
fileInfo:TEntry):boolean;
Type Treq=record
len :word;
subFunc :byte;
_Fattr,
_ExtFattr :Byte;
reserved1 :LongInt; {hi-lo}
_crDate :word; {hi-lo}
_lastAccDate :word; {hi-lo}
_lastUpdTime :Longint;
_ownerObjId :Longint; {hi-lo}
_lastArchTime:Longint;
reserved2 :array[1..56] of byte;
_dirHandle :Byte;
_searchAttr :byte;
_filePath :string;
end;
TPreq=^Treq;
Var DummyDate:Longint;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$10;
_Fattr:=Lo(LowLong(fileInfo.Attributes));
_ExtFattr:=Hi(LowLong(fileinfo.Attributes));
_ownerObjId:=Lswap(fileinfo.OwnerId); {force hi-lo}
_dirHandle:=DirHandle;
_searchAttr:=SearchAttrib;
_filePath:=FilePath;
If Dirhandle=0
then ConvertPathToVolFormat(_FilePath);
UpString(_filePath);
NovTime2DosTime(fileinfo.CreationTime,dummyDate);
_crDate:=HiLong(dummyDate);
NovTime2DosTime(fileinfo.LastAccessTime,dummyDate);
_lastAccDate:=HiLong(dummyDate);
NovTime2DosTime(fileinfo.ModifyTime,_lastUpdTime);
NovTime2DosTime(fileinfo.ArchiveTime,_lastArchTime);
len:=82+ord(_filepath[0]);
F2SystemCall($17,len+2,0,result);
end;
SetFileInformation:=(result=0);
{ result codes: 00 Success }
end;
{F244 [2.1x/3.x]}
Function EraseFiles(dirHandle, searchAttrib:Byte; filePath:string ):boolean;
{ marks files for deletion / in DOS parlance: delete file, file remains purgable }
Type Treq=record
_dirHandle:Byte;
_Sattr:Byte;
_filePath:string;
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
_dirHandle:=dirHandle;
_Sattr:=searchAttrib;
_filePath:=filePath;
F2SystemCall($44,3+ord(_filepath[0]),0,result);
end;
EraseFiles:=(result=0);
{ resultcodes: 00 Success; 98h Volume doesn't exist; 9Bh bad directory handle;
9Ch invalid path; FFh no files found error. }
end;
{F216/1B [3.0+]}
Function ScanSalvagableFiles(DirHandle:Byte;
{i/o} Var EntryId:Longint;
{out} Var Entry:Tentry ):boolean;
{ Iterate (with entryId set to -1 at first) until an error $FF occurs }
Type Treq=record
len :word;
subFunc :byte;
_DirHandle:Byte;
_EntryId :Longint; {low_word-hi_word & each word lo-hi }
end;
Trep=record
_EntryId :Longint;
_Entry :TintEntry;
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$1B;
_DirHandle:=DirHandle;
_EntryId:=EntryId;
end;
F2SystemCall($16,SizeOf(Treq),Sizeof(Trep),result);
With TPrep(GlobalReplyBuf)^
do begin
EntryId:=_EntryId; {return next EntryId for iteration}
{low_word-hi_word & each word lo-hi }
Convert2ExtEntry(_Entry,Entry);
end;
ScanSalvagableFiles:=(result=0)
{ 98 Volume does not exist FF No more erased files }
end;
{F216/1D [3.0+]}
Function PurgeSalvagableFile(DirHandle:Byte;
EntryId:Longint; FileName:string):boolean;
{ either supply an entryId and an empty filename,
or supply an entryId of -1 and a filename. Note that the filename
may not be unique: there may be more than one old deleted versions
of a filename. }
Type Treq=record
len :word;
subFunc :byte;
_DirHandle:Byte;
_EntryId :Longint; {low_word-hi_word & each word lo-hi }
_Name :string[255];
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$1D;
_DirHandle:=DirHandle;
_EntryId:=EntryId;
_Name:=FileName;
UpString(_name);
len:=7+ord(_Name[0]);
F2SystemCall($16,len+2,0,result);
end;
PurgeSalvagableFile:=(result=0)
end;
{F216/1C [3.0+] }
Function RecoverSalvagableFile(dirHandle:Byte; EntryId:Longint;
OldName,NewName:string):boolean;
{ entryId may be set to -1
OldName is the name of the file before it was deleted.
NewName is the name to be assigned to the recovered file }
Type Treq=record
len :word;
subFunc :byte;
_DirHandle :Byte;
_EntryId :Longint; {low_word-hi_word & each word lo-hi }
_OldAndNewName:string[255];
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$1C;
_DirHandle:=DirHandle;
_EntryId:=EntryId;
UpString(OldName);
UpString(NewName);
_OldAndNewName:=OldName;
move(NewName[0],_OldAndNewName[ord(oldname[0])+1],ord(NewName[0])+1);
len:=8+ord(oldName[0])+ord(NewName[0]);
F2SystemCall($16,len+2,0,result);
end;
RecoverSalvagableFile:=(result=0)
{ 98 Volume does not exist FF No more erased files }
end;
{F216/24 [3.0+]}
Function SetDirRestriction(DirHandle:Byte; DiskSpaceLimit:Longint):boolean;
{ limit expressed in Blocks. set limit to 0 to lift limit.
use a negative number if limit should be equal to 0 }
Type Treq=record
len :word;
subFunc :byte;
_DirHandle:Byte;
_Limit :Longint;
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$24;
_DirHandle:=DirHandle;
_Limit:=DiskSpaceLimit;
end;
F2SystemCall($16,SizeOf(Treq),0,result);
SetDirRestriction:=(result=0)
end;
{F216/23 [3.0+]}
Function ScanDirRestrictions(DirHandle:Byte;
Var NumberOfEntries:Byte;
Var RestrInfo:TdirRestrList):boolean;
Type Treq=record
len:word;
subFunc:byte;
_DirHandle:Byte;
end;
Trep=record
_Entries:Byte;
_Info:TdirRestrList;
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$23;
_DirHandle:=DirHandle;
end;
F2SystemCall($16,SizeOf(Treq),Sizeof(Trep),result);
With TPrep(GlobalReplyBuf)^
do begin
NumberOfEntries:=_Entries;
RestrInfo:=_Info;
end;
ScanDirRestrictions:=(result=0)
end;
Procedure FixEntryNameFormat(Var s:string);
Var res:string;
p:byte;
begin
res:='';
for p:=1 to ord(s[0])
do begin
if s[p]='?'
then res:=res+#$FF+#$BF
else if s[p]='*'
then res:=res+#$FF+'*'
else res:=res+s[p]
end;
s:=res;
end;
{F216/1E [2.15c+]}
Function ScanDirectoryEntry(DirHandle:Byte; EntryName:string; SearchFlags:Longint;
{i/o} Var EntryId:Longint;
{out} Var Entry:Tentry ):boolean;
Type Treq=record
len :word;
subFunc :byte;
_DirHandle :Byte;
_SearchFlags:Byte; { standard: $16 for dirs / $06 for files }
_SeqNbr :Longint; { lo-hi , set to -1 initially }
_EntryName :string;
end;
Trep=record { len = 84h = 132 dec. }
_EntryID :Longint; { lo-hi }
_Entry :TintEntry;
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$1E;
_DirHandle:=DirHandle;
_SearchFlags:=SearchFlags;
_SeqNbr:=EntryId;
_EntryName:=EntryName;UpString(_EntryName);
FixEntryNameFormat(_EntryName);
len:=8+ord(_EntryName[0]);
F2SystemCall($16,len+2,Sizeof(Trep),result);
end;
With TPrep(GlobalReplyBuf)^
do begin
EntryId:=_EntryId; {return next EntryId for iteration}
Convert2ExtEntry(_Entry,entry);
end;
ScanDirectoryEntry:=(result=0)
end;
{F216/25 [2.15c+] }
Function SetEntry(DirHandle:Byte;EntryId:Longint;SearchFlags:Byte;
ModFlags:Longint; Entry:Tentry ):boolean;
Type Treq=record
len :word;
subFunc :byte;
_dirHandle:Byte;
_SFlags :Byte;
_EntryId :Longint; {lo-hi}
_ModFlags :Longint; {lo-hi}
_Entry :TintEntry;
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$25;
_dirHandle:=DirHandle;
_EntryId:=EntryId;
_ModFlags:=ModFlags;
Convert2IntEntry(Entry,_Entry);
end;
F2SystemCall($16,SizeOf(Treq),0,result);
SetEntry:=(result=0)
end;
{------------------ Secondary Functions ----------------------------}
Function IsFileShareable(Path : String):boolean;
var F: File;
FAttr : Word;
begin
{ Assign(F, Path);
GetFAttr(F, FAttr);
result:=DOSerror; }
IsFileShareable:=(result=0) and ((FAttr and $80)>0)
end;
function FlagFileShareable(Path : String) : Boolean;
{ when the file could NOT be made shareable, false is returned as the
function result, a doserror# is returned as the result code. }
var F : File;
Attr : Word;
ErrCode : word;
Share : Boolean;
begin
if NOT IsFileShareable(Path) { Share: is it sharable? }
then begin
Assign(F,Path);
{SetFAttr(F,Attr or A_SHAREABLE); OR existing atrib. with SHARE bit }
{Result := DOSError;}
end;
FlagFileShareable := (Result=0);
end;
Function GetFileHandle(Var f):word;
begin
{GetFileHandle:=filerec(f).handle;}
end;
{------===================-- Trustee/Max. Rights masks --=================--}
{F216/27 [3.0+]}
Function SetTrustee(DirHandle:Byte;DirPath:string;
TrusteeObjectID:Longint;
RightsMask:Word ):boolean;
Type Treq=record
len :word;
subFunc :byte;
_DirHandle:byte;
_ObjId :Longint; { hi-lo }
_Rights :Word; { lo-hi }
_DirPath :string;
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$27;
_DirHandle:=DirHandle;
if DirHandle=0
then ConvertPathToVolFormat(DirPath);
_DirPath:=DirPath;UpString(_DirPath);
_ObjId:=Lswap(TrusteeObjectId);
_Rights:=RightsMask;
len:=9+ord(_DirPath[0]);
F2SystemCall($16,len+2,0,result);
end;
SetTrustee:=(result=0)
{ Possible resultcodes: 8C No modify privileges;
98 Volume doesn't exist; 9B Bad directory handle
9C Invalid path; FC No such bindery object }
end;
{F216/2B [3.0+]}
Function DeleteTrustee(DirHandle:Byte;DirPath:String;
TrusteeObjectId:Longint):boolean;
{ If DirHandle equals 0, DirPath should be according to the
VOL:\path format. All other path formats will result in
an resultcode of 98h (No such volume) }
Type Treq=record
len :word;
subFunc :byte;
_DirHandle:byte;
_ObjId :Longint; { hi-lo }
_Unused :Byte;
_DirPath :string;
end;
TPreq=^Treq;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
subFunc:=$2B;
_DirHandle:=DirHandle;
if DirHandle=0
then ConvertPathToVolFormat(DirPath);
_DirPath:=DirPath;UpString(_DirPath);
_ObjId:=Lswap(TrusteeObjectId);
_Unused:=0;
len:=8+ord(_DirPath[0]);
F2SystemCall($16,len+2,0,result);
end;
DeleteTrustee:=(result=0);
{ Possible resultcodes: 98 Volume doesn't exist
9B Bad directory handle; 9C Invalid path
FE no such trustee }
end;
{F216/2A [3.0+]}
function GetEffectiveRights(DirHandle:Byte;DirPath:String;
var Rights:Word) : Boolean;
{ returns the requesting workstation's effective directory rights }
Type Treq=record
Len : word;
SubF : Byte;
_DirHandle : Byte;
_DirName : String;
end;
TRep=record
_RightsMask : Word;
end;
TPreq=^Treq;
TPrep=^Trep;
begin
with TPreq(GlobalReqBuf)^
do begin
SubF := $2A;
_DirHandle := DirHandle;
if DirHandle=0
then ConvertPathToVolFormat(DirPath);
_DirName := DirPath;UpString(_DirName);
Len := 3+ord(DirPath[0]);
F2SystemCall($16,len+2,SizeOf(Trep),result);
end;
with TPrep(GlobalReplyBuf)^
do Rights:=_RightsMask;
GetEffectiveRights:=(Result=0);
{ return byte
00h - Success
98h - Volume Does Not Exist
9Bh - Bad Directory Handle }
end;
{F216/04 [2.15c+]}
Function ModifyMaximumRightsMask(DirHandle:Byte;DirPath:string;
RevokeRightsMask,GrantRightsMask:Word):boolean;
Type Treq=record
len:word;
subFunc:byte;
_DirHandle:Byte;
_GrantRM,
_RevokeRM:Byte;
_DirPath:String;
end;
Trep=record
_EffectiveRightsMask:Byte;
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=5+ord(DirPath[0]);
subFunc:=$04;
_DirHandle:=DirHandle;
if DirHandle=0
then ConvertPathToVolFormat(DirPath);
_GrantRM:=MapV3RightsToV2(GrantRightsMask);
_RevokeRM:=MapV3RightsToV2(RevokeRightsMask);
_DirPath:=DirPath;
F2SystemCall($16,len+2,Sizeof(Trep),result);
end;
{With TPrep(GlobalReplyBuf)^
do begin
--- nothing is done with the returned value---
end;}
ModifyMaximumRightsMask:=(result=0)
{ result codes: 8C No modify privileges; 98 Volume dosn't exist;
9C Invalid path }
end;
{F217/47 [2.15c+]}
Function ScanBinderyObjectTrusteePaths(TrusteeObjectId:Longint;
VolumeNumber:Byte;
{i/o} Var SequenceNumber:word;
{out} Var AccessMask:Word;
Var Path:string ):boolean;
{ You must be supervisor (-equivalent) or the TrusteeObject itself
to use this function.
Initially, sequencenumber should be set to 0. }
Type Treq=record
len :word;
subFunc:byte;
_VolNbr:Byte;
_SeqNbr:word; {hi-lo}
_ObjId :Longint; {hi-lo}
end;
Trep=record
_NextSeqNbr:Word; {hi-lo}
_ObjId :Longint; {hi-lo}
_AccMask :byte;
_Path :string;
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$47;
_VolNbr:=VolumeNumber;
_SeqNbr:=swap(SequenceNumber);
_ObjId:=Lswap(TrusteeObjectId);
end;
F2SystemCall($17,SizeOf(Treq),Sizeof(Trep),result);
With TPrep(GlobalReplyBuf)^
do begin
SequenceNumber:=Lswap(_NextSeqNbr);
Accessmask:=_AccMask; {MapV2RightsToV3(_accMask);}
Path:=_Path;
end;
ScanBinderyObjectTrusteePaths:=(result=0)
{ resultcodes:
$96 Server out of memory; $F0 Wildcard not allowed;
$F1 Invalid bindery security; $FC No such object;
$FE Server bindery locked; $FF Bindery failure }
end;
{F216/26 [3.0+]}
Function ScanEntryForTrustees(DirHandle:Byte;DirPath:String;
{i/o} Var SequenceNumber:Byte;
{out} Var TrusteeInfo: TtrusteeInformation):boolean;
{ Set SequenceNumber to 0 initially,
iterate until error $9C (no more trustees) is returned }
{ see GETTR in the XFILE archive for an example }
Type Treq=record
len:word;
subFunc:byte;
_DirHandle:Byte;
_SeqNbr:Byte;
_DirPath:String;
end;
Trep=record
_Info:TtrusteeInformation;
end;
TPreq=^Treq;
TPrep=^Trep;
Var t:Byte;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=4+ord(DirPath[0]);
subFunc:=$26;
_DirHandle:=DirHandle;
if DirHandle=0
then ConvertPathToVolFormat(DirPath);
_SeqNbr:=SequenceNumber;
_DirPath:=DirPath;UpString(_DirPath);
F2SystemCall($16,len+2,Sizeof(Trep),result);
end;
With TPrep(GlobalReplyBuf)^
do begin
inc(SequenceNumber);
TrusteeInfo.NumberOfTrustees:=_Info.NumberOfTrustees;
for t:=1 to 20
do begin
TrusteeInfo.TrusteeId[t]:=Lswap(_Info.TrusteeId[t]);
TrusteeInfo.TrusteeRights[t]:=_Info.TrusteeRights[t];
end;
end;
ScanEntryForTrustees:=(result=0)
{ resultcodes:
$9C No more trustees }
end;
{F2 [2.15c+]
Function ( ):boolean;
Type Treq=record
len:word;
subFunc:byte;
end;
Trep=record
end;
TPreq=^Treq;
TPrep=^Trep;
Begin
WITH TPreq(GlobalReqBuf)^
do begin
len:=SizeOf(Treq)-2;
subFunc:=$
end;
F2SystemCall($ ,SizeOf(Treq),Sizeof(Trep),result);
With TPrep(GlobalReplyBuf)^
do begin
end;
:=(result=0)
end; }
end.